import { newArrayProto } from './array'

class Observer {
  constructor(data) {
    // 给数据添加标识，表示已经观测了，不能直接加，会死循环
    Object.defineProperty(data, '__ob__', {
      enumerable: false,
      value: this
    })
    if (Array.isArray(data)) {
      // 数组不能逐项添加 getter setter 因为可能太多，耗费性能，更好的办法是劫持部分变异方法
      // 同时 [1,2,3 { num:1 }] 里的 obj 也应该被劫持
      data.__proto__ = newArrayProto
      this.observeArray(data)
    } else {
      this.walk(data)
    }
  }

  walk(data) {
    // 重新定义 data 的属性，存在性能问题
    Object.keys(data).forEach((key) => defineReactive(data, key, data[key]))
  }

  observeArray(data) {
    data.forEach((item) => observe(item))
  }
}

export function defineReactive(target, key, value) {
  // 对 value 进行递归观测
  observe(value)
  Object.defineProperty(target, key, {
    get() {
      console.log('get', key)
      return value
    },

    set(newValue) {
      if (newValue === value) return
      observe(newValue)
      value = newValue
    }
  })
}

// 观测函数
export function observe(data) {
  // 只处理对象
  if (typeof data !== 'object' || data == null) return

  if (data.__ob__ instanceof Observer) {
    return data.__ob__
  }

  return new Observer(data)
}
